iT邦幫忙

2021 iThome 鐵人賽

DAY 13
1
Software Development

溫柔學姐的Kotlin補課/教學系列 第 13

危險氣息的研究室:尾遞迴 Tail Calls

  • 分享至 

  • xImage
  •  

研究生和大學生不同,跟著指導的教授有著獨立的研究室,以滯留時間來看,可說是研究生的第二個家。

「吶,小唯心,最近的學生是不是太死背考古題了啊。」某個教授閒來沒事,和自己的研究生發牢騷。

「誰叫教授們為求省事,使用題庫呢,要不然這次改出新題?」唯心一邊整理數據,一邊淡淡回應。

「咦?麻煩?只要確認學生能按要求寫出合格的程式就好了吧。」翁玉慵懶地玩弄自己的頭髮。

「恕我直言,教授講解的尾遞迴也不知道有多少學生聽懂,說不定連根本的遞迴也沒弄清楚。」

翁玉疑惑地轉過頭。「不是吧?遞迴就是函式在執行過程裡又呼叫自己,這個也不懂的話,現在的學生真的沒問題嗎?」

「教授妳忘記這次的選課開放新生和外系了嗎?」唯心善意提醒。

「難怪這次教室裡的女孩子比以往多。那為了讓他們明白,也許放些實際例子會比較容易理解吧。現在的高中數學有哪些可以用的例子?」

唯心回想了一下,答道:「費氏數列和階乘吧?」

「那就選階乘好了,費氏數列要呼叫自己兩次,還要數位置,比較難懂吧?」翁玉戳著唯心養的仙人掌,仙人掌的軟刺觸感甚得她心。

fun 費氏數列(n: Int): Int {
    return if (n < 2) { n }
    else 費氏數列(n - 1) + 費氏數列(n - 2)
}

唯心迅速救走仙人掌盆栽。「也因為呼叫多次,改寫成尾遞迴的優勢才明顯啊。毀滅性的Stack Overflow Error不就是因為遞迴呼叫產生的堆疊太多,還沒回收回來就爆掉了。」唯心頓了一下。「說起來堆疊是在資料結構課程的範圍,如果教授妳要推廣尾遞迴,那就要讓他們認識堆疊了。」

「要從那裡開始嗎⋯⋯」翁玉無語。

唯心聯想到她和詩憶的補課方式,於是提議:「或許可以說的籠統一點,比如說,每次呼叫函式都會佔據一單位記憶體,當函式執行完才能回收記憶體,所以在執行期間呼叫多個自己的遞迴就會佔據大量記憶體,最後記憶體滿了程式就掛了。尾遞迴算是先和程式約好每次最多只能呼叫一次自己,也不能用到其他資源,所以程式能準備重複利用記憶體的機制。」

fun 階乘(n: Int): Int {
    return if (n < 2) { n }
    else n * 階乘(n - 1)//因為還帶了 n * 所以只是普通的遞迴
}

tailrec fun 階乘尾遞迴(n: Int, tail: Int = 1): Int {
    return if (n < 2) { tail }
    else 階乘尾遞迴(n - 1, n * tail)
}

「是呀,也不是所有程式語言都能支援尾遞迴,Java8就不行。說起來小唯心怎麼知道有同學不懂尾遞迴?」翁玉突然想到這個問題。

「因為有不少同學拿著程式碼來問我他寫的是不是尾遞迴呀,呵呵。」對面傳來有點陰森的笑聲。「我和他們說,在函式前面加上tailrec執行看看,IDE發現不對勁就會發警告。」

「嗯,很好的方法。對了,像之前一樣讓學生來這裡找妳也可以唷。」翁玉話才說完,感覺室內溫度立即下降了幾度。「⋯⋯我有事先走了,下次見唷小唯心。」不能再待在這間越發散發危險氣息的研究室哩。


上一篇
實作四則運算:條件式 when else
下一篇
重複的專家:迴圈 repeat , for loop, while loop, do while loop
系列文
溫柔學姐的Kotlin補課/教學31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言